Multiperiod Financial Models

FROM - Operations Research: Applications and Algorithms 4th Edition, p105, Wayne L. Winston

Finco Investment Corporation must determine investment strategy for the firm during the next three years. Currently (time 0), \$100,000 is available for investment. Investments A, B, C, D, and E are available. The cash flow associated with investing \$1 in each investment is given in Table.

For example, \$1 invested in investment B requires a \$1 cash outflow at time 1 and returns 50cents at time 2 and $1 at time 3. To ensure that the company’s portfolio is diversified, Finco requires that at most \$75,000 be placed in any single investment. In addition to investments A-E, Finco can earn interest at 8% per year by keeping uninvested cash in money market funds. Returns from investments may be immediately reinvested. For example, the positive cash flow received from investment C at time 1 may immediately be reinvested in investment B. Finco cannot borrow funds, so the cash available for investment at any time is limited to cash on hand. Formulate an LP that will maximize cash on hand at time 3.


In [5]:
from gurobipy import *

time_period = ["t1", "t2", "t3", "t4"]
invement_targets = ["A", "B", "C", "D", "E"]
slacks = ["S0", "S1", "S2"]
all_variables = invement_targets+slacks

m = Model("multiperiod_investment")

slacks_interest = [0, 0, 1.08]

cash_flow = [
    [100000, -1, 0 , -1, -1, 0, -1, 0, 0],
    [0, 0.5, -1 , 1.2, 0, 0, 1.08, -1, 0],
    [0, 1, 0.5 , 0, 0, -1, 0, 1.08, -1],
    [0, 0, 1 , 0, 1.9, 1.5, 0, 0, 1.08]
]

variables = [1]
for i in range(len(all_variables)):
    variables.append(
        m.addVar(vtype=GRB.CONTINUOUS, obj = cash_flow[3][i+1], name="(cash-%s)" % (all_variables[i])))

    
m.modelSense = GRB.MAXIMIZE
m.update()

for time in range(len(cash_flow)-1):
    m.addConstr(quicksum(cash_flow[time][i] * variables[i] for i in range(len(cash_flow[time]))) == 0, 
                "constraints %s" % variables[time])

for targes_index in range(len(invement_targets)):
    m.addConstr(variables[targes_index+1]  <= 75000, 
                "totalinvesment regulation %s" % variables[targes_index])

m.optimize()

for v in m.getVars():
    print (v.varName, v.x)

    
print (m.getObjective().getValue())


1
1
1
Optimize a model with 8 rows, 8 columns and 19 nonzeros
Coefficient statistics:
  Matrix range     [5e-01, 1e+00]
  Objective range  [1e+00, 2e+00]
  Bounds range     [0e+00, 0e+00]
  RHS range        [8e+04, 1e+05]
Presolve removed 5 rows and 0 columns
Presolve time: 0.01s
Presolved: 3 rows, 8 columns, 14 nonzeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    7.2658339e+05   5.587216e+05   0.000000e+00      0s
       3    2.1850000e+05   0.000000e+00   0.000000e+00      0s

Solved in 3 iterations and 0.01 seconds
Optimal objective  2.185000000e+05
(cash-A) 60000.0
(cash-B) 30000.0
(cash-C) 0.0
(cash-D) 40000.0
(cash-E) 75000.0
(cash-S0) 0.0
(cash-S1) 0.0
(cash-S2) 0.0
218500.0